package apibasej.infra;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.logging.Level;

import apibasej.basic.InterfaceExec;
import apibasej.basic.config.ConfigManager;
import apibasej.basic.misc.UtilTrace;

public abstract class ExecSocket extends ConfigManager implements InterfaceExec{

	private Socket socket;
	private SimpleServerSocket<?> simpleServerSocket;

	public abstract void execSocket() throws Throwable;
	
	@Override
	public void exec() {
		try{
			execSocket();
		}catch (Throwable e) {
			String m = "Error on execute: "+getClass().getName();
			logDef(Level.SEVERE,m,e);
			getSimpleServerSocket().tryReturnError(getSocket(), UtilTrace.getStackTrace(m, e));
		}finally{
			close();
		}
	}
	
	private InputStream inputStream;
	public InputStream getInputStream() throws IOException {
		if(inputStream==null){
			inputStream = getSocket().getInputStream();
		}
		return inputStream;
	}
	
	private OutputStream outputStream;
	public OutputStream getOutputStream() throws IOException {
		if(outputStream==null){
			outputStream = getSocket().getOutputStream();
		}
		return outputStream;
	}

	// deve ser chamado logo após criar a classe
	public void setSocket(Socket socket) {
		this.socket = socket;
	}
	public Socket getSocket() {
		return socket;
	}
	public SimpleServerSocket<?> getSimpleServerSocket() {
		return simpleServerSocket;
	}
	public void setSimpleServerSocket(SimpleServerSocket<?> simpleServerSocket) {
		this.simpleServerSocket = simpleServerSocket;
	}

	public void close(){
		if(inputStream!=null){
			try {
				inputStream.close();
			} catch (Exception e) {
				logDef(Level.SEVERE,"Error on close Socket InputStream",e);
			}
		}
		if(outputStream!=null){
			try {
				 outputStream.close();
			} catch (Exception e) {
				logDef(Level.SEVERE,"Error on close Socket OutputStream",e);
			}
		}
		if(socket!=null && !socket.isClosed()) {
			try {
				socket.close();
			} catch (Exception e) {
				logDef(Level.SEVERE,"Error on close Socket",e);
			}
		}
		
	}

}
